# -*- coding: utf-8 -*-
from enum import Enum
from typing import Any, Optional
from datetime import datetime, timedelta

import base64
import requests

from bct.tools.common.bct_util import get_logger
from bct.tools.common.url_builder import url_builder

logger = get_logger("bct3_client")


class BCT3Ver(Enum):
    SWHY = '0'


def login(username: str, password: str, host: str, port: int, method: str = None) -> dict:
    """
    登陆
    :param username: 登陆用户名
    :param password: 登陆密码
    :param host: 服务器地址
    :param port: 服务器端口
    :param method: 如果设为base64的话，会对用户名密码进行base64
    :return: 登陆头，包含了访问所需的token
    """
    url = '%s/auth-service/users/login' % url_builder(host, port)
    user = username
    pwd = password
    logger.info("login with %s" % (user))
    if method == 'base64':
        user = base64.b64encode(username.encode(encoding='utf-8')).decode(encoding='utf-8')
        pwd = base64.b64encode(password.encode(encoding='utf-8')).decode(encoding='utf-8')
    body = {
        'username': user,
        'password': pwd
    }
    res = requests.post(url, json=body)
    try:
        json = res.json()
        logger.info("login success")
        logger.info("token:%s" % json['result']['token'])
    except Exception as e:
        print(e)
        print('\t=>' + res.text)
        print(res.headers)
        raise RuntimeError('error logging in: ')
    if 'error' in json:
        raise RuntimeError('error logging in: ' + json['error']['message'])
    token = json['result']['token']
    headers = {
        'Authorization': 'Bearer ' + token
    }
    return headers


def call_request(host: str, port: int, service: str, method: str, params: dict, headers: dict) -> Any:
    """
    发送请求
    :param host:
    :param port:
    :param service:
    :param method:
    :param params:
    :param headers:
    :return:
    """
    url = '%s/%s/api/rpc' % (url_builder(host, port), service)

    body = {
        'method': method,
        'params': params
    }

    try:
        res = requests.post(url, json=body, headers=headers)
        if res.status_code != 200:
            logger.error("rest call failed, status code: %s", 200)
            return None
        json = res.json()
        if 'error' in json:
            if 'message' in json['error'] and json['error']['message'] is not None:
                logger.error("failed execute %s convertor:%s,error:%s", method, host, json['error']['message'])
            else:
                logger.error("failed execute %s convertor:%s,error: no msg", method, host)
            return 'error'
        else:
            logger.info("success execute %s,callRequest:%s convertor %s", method, str(len(params)), host)
            return json
    except Exception as e:
        logger.info("failed execute %s convertor %s Exception:%s", method, host, str(e))
        raise e


def trans_datetime(time_str: str) -> datetime:
    date_str = datetime.now().strftime('%Y-%m-%d')
    datetime_str = date_str + 'T' + time_str
    datetime_time = datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%S')
    return datetime_time


def trans_utc_datetime(time_str: str) -> datetime:
    """
    减8小时
    :param time_str:
    :return:
    """
    date_str = datetime.now().strftime('%Y-%m-%d')
    datetime_str = date_str + 'T' + time_str
    datetime_time = datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%S')
    return datetime_time - timedelta(hours=8)


class BCT3Client:
    server_url: str
    server_port: int
    script_name: str
    script_password: str
    login_header: Optional[dict] = None
    bct3_ver: BCT3Ver

    def login(self, base64enabled: Optional[bool] = True):
        """
        以脚本用户登录
        :return: header
        """
        if base64enabled:
            self.login_header = login(self.script_name, self.script_password, self.server_url, self.server_port,
                                      'base64')
        else:
            self.login_header = login(self.script_name, self.script_password, self.server_url, self.server_port)

    def fetch_trade(self, lcm_event_type: Optional[str] = None, page: int = 0, page_size: int = 15) -> dict:
        """
        分页获取交易
        :param lcm_event_type: UNWIND_PARTIAL,OPEN,UNWIND
        :param page:
        :param page_size:
        :return:
        """
        result = call_request(self.server_url,
                              self.server_port,
                              'trade-service',
                              'trdTradeSearchIndexPaged',
                              {
                                  'lcmEventType': lcm_event_type,
                                  'page': page,
                                  'pageSize': page_size
                              },
                              self.login_header).get('result', {})
        return {
            'totalCount': result.get('totalCount', 0),
            'page': result.get('page', [])
        }

    def __init__(self, server_url: str, script_name: str, script_password: str, server_port=80,
                 bct3_ver: BCT3Ver = BCT3Ver.SWHY):
        """
        初始化客户端
        :param server_url: 服务器地址 http://xxxx.xxx.xxx
        :param script_name:  脚本用户名
        :param script_password: 脚本用户密码
        :param bct3_ver: 特定的bct3ver
        """
        self.bct3_ver = bct3_ver
        self.server_url = server_url
        self.script_name = script_name
        self.script_password = script_password
        self.server_port = server_port
        self.login()
